home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / ccmd / ccmdmd.dos < prev    next >
Encoding:
Text File  |  1988-08-19  |  9.4 KB  |  376 lines

  1. /*
  2.  Author: Andrew Lowry
  3.  
  4.  Columbia University Center for Computing Activities, July 1986.
  5.  Copyright (C) 1986, 1987, Trustees of Columbia University in the City
  6.  of New York.  Permission is granted to any individual or institution
  7.  to use, copy, or redistribute this software so long as it is not sold
  8.  for profit, provided this copyright notice is retained.
  9. */
  10.  
  11. /* Machine dependent code for systems running under MS-DOS.
  12. ** Assumes ANSI.SYS has been installed as an installable device
  13. ** driver.  For any version or compiler peculiarities, use 
  14. ** preprocessor conditionals, but PLEASE -- do not nest
  15. ** conditionals!
  16. */
  17.  
  18. #include "ccmd.h"        /* get ccmd symbols */
  19. #include "cmfncs.h"        /* and internal symbols */
  20.  
  21.  
  22.  
  23. /* cmrpjmp
  24. **
  25. ** Purpose:
  26. **   Automatic reparse handler, installed via the cmsetrp macro from
  27. **   ccmd.h.  If this handler is installed in a CSB for which a reparse
  28. **   is needed, it will perform a longjmp to restart execution at the
  29. **   point following the installing cmsetrp invocation.  This point
  30. **   should be following the call to cmini that set up parsing for
  31. **   the current command line, and before the comnd call for the first
  32. **   field in the command.
  33. **
  34. ** Input arguments: None
  35. ** Output arguments: None
  36. ** Returns: Nothing
  37. **/
  38.  
  39.  
  40. jmp_buf cmrpjb;            /* global jump buffer for autoreparse */
  41.  
  42. cmrpjmp()
  43. {
  44. #ifdef LATTICE
  45.   longjmp(&cmrpjb,1);        /* do the jump */
  46. #else
  47.   longjmp(cmrpjb,1);
  48. #endif
  49.   return(CMxNOAR);        /* if it returns, it failed */
  50. }
  51.  
  52.  
  53.  
  54. /* cmerjmp
  55. **
  56. ** Purpose:
  57. **   Automatic parse error handler, much like the automatic reparse
  58. **   handler described above.  This macro should be invoked just prior
  59. **   to issuing a prompt.  When a parsing error subsequently occurs
  60. **   (that is, the parse function is about to return anything but
  61. **   CMxOK), cmperr will be called to print the error, and then
  62. **   execution will jump back to the site of this macro.  When the
  63. **   automatic error handler is installed, the user program can
  64. **   ignore the codes returned by parse, since they will always be
  65. **   CMxOK.
  66. **
  67. **   Note: Reparse situations will be handled by the error handler if
  68. **   no reparse handler has been installed.
  69. **
  70. ** Input arguments: None.
  71. ** Output arguments: None.
  72. ** Returns: Nothing.
  73. **/
  74.  
  75. jmp_buf cmerjb;                /* global jump buffer */
  76.  
  77. cmerjmp(ret)
  78. int ret;                /* code that triggered the handler */
  79. {
  80.   cmperr(ret);                /* issue error message */
  81. #ifdef LATTICE
  82.   longjmp(&cmerjb,1);            /* take the jump */
  83. #else
  84.   longjmp(cmerjb,1);
  85. #endif
  86.   return(CMxNOAE);            /* failed */
  87. }
  88.  
  89. cmerjnp(ret)
  90. int ret;                /* code that triggered the handler */
  91. {
  92. #ifdef LATTICE
  93.   longjmp(&cmerjb,1);            /* take the jump */
  94. #else
  95.   longjmp(cmerjb,1);
  96. #endif
  97.   return(CMxNOAE);            /* failed */
  98. }
  99.  
  100.  
  101. /*
  102.  * if handling nonblocking I/O, and a BLOCKING error comes up
  103.  * Then jump to the point set with a cmsetbl() call.
  104.  * The user then could wait for input.
  105.  */
  106.  
  107. jmp_buf cmbljb;                /* global jump buffer */
  108.  
  109. cmbljmp(ret)
  110. int ret;                /* code that triggered the handler */
  111. {
  112.   /*
  113.    * how to check for a blocking error here?
  114.    */
  115.   return(ret);                /* for now, ignore */
  116. #ifdef LATTICE
  117.   longjmp(&cmbljb,1);            /* take the jump */
  118. #else
  119.   longjmp(cmbljb,1);            /* take the jump */
  120. #endif
  121.   return(CMxNOAE);            /* failed */
  122. }
  123.  
  124.  
  125.  
  126. /*
  127. ** Machine-dependent IO routines... In each case, if the file descriptor
  128. ** argument is the special value CONSOLE, the IO is done to the console
  129. ** using Lattice C's direct console I/O routines.  If the file descriptor
  130. ** is not CONSOLE but nevertheless refers to the console, the direct
  131. ** console I/O operations will also be used.  Any other file descriptor
  132. ** is assumed NOT to refer to a terminal, so no echoing will be performed.
  133. ** In this case, the user program may want to set CM_TTY and/or CM_CRT 
  134. ** in order to cause normal terminal handling.  If CRT is set in this
  135. ** case, a dumb crt will be assumed, which does automatic wraparound
  136. ** at the right border and which has no screen functions other than
  137. ** character output, carriage return, linefeed, backspace, and
  138. ** destructive space.
  139. **/
  140.  
  141. static int console;            /* TRUE if source is console */
  142.  
  143. /* cmgetc - get a character from the input source.  Return std return code */
  144.  
  145. int
  146. cmgetc(c,fd)
  147. char *c;            /* pointer where input char is placed */
  148. FILE *fd;            /* input filedesc */
  149. {
  150.   int cc;            /* int returned by system routines */
  151.  
  152.   if (console) {
  153.     *c = getch();
  154.     return(CMxOK);
  155.   }
  156.   if (cmcsb._cmoj != NULL)
  157.     fflush(cmcsb._cmoj);
  158.   if (fd == NULL)
  159.     return(CMxEOF);
  160.   *c = getc(fd);
  161.   if (*c == EOF)
  162.     return(CMxEOF);
  163.   return(CMxOK);
  164. }
  165.  
  166. /* cmputc - Output a single character to the terminal */
  167.  
  168. cmputc(c,fd)
  169. char c;                /* character to output */
  170. FILE *fd;            /* input filedesc */
  171. {
  172.   if (console) {
  173.     if (c == '\n')
  174.       putch('\r');
  175.     putch(c);
  176.   }
  177.   else {
  178.     if (fd != NULL) {
  179.       putc(c,fd);
  180.       if (c == '\n')
  181.     fflush(fd);
  182.     }
  183.   }
  184. }
  185.  
  186. /* cmputs - Output null-terminated string to the terminal */
  187.  
  188. cmputs(s,fd)
  189. char *s;            /* string to output */
  190. FILE *fd;            /* output filedesc */
  191. {
  192.   while(*s != NULL) {
  193.     cmputc(*s,fd);
  194.     *s++;
  195.   }
  196. }
  197.  
  198. /* cmcr - Move to the beginning of the current line */
  199.  
  200. cmcr(fd)
  201. FILE *fd;            /* input filedesc */
  202. {
  203.   cmputc(RETURN,fd);        /* output a carriage return */
  204. }
  205.  
  206. /* cmnl - Output a newline sequence to the command stream */
  207.  
  208. cmnl(fd)
  209. FILE *fd;            /* input filedesc */
  210. {
  211.   cmputc(NEWLINE,fd);        /* just a newline character */
  212. }
  213.  
  214. /* cmflsh - flush output on fd */
  215. cmflsh(fd)
  216. FILE *fd;
  217. {
  218.   if (fd != NULL)
  219.     fflush(fd);
  220. }
  221.  
  222. /* cmwrap - Make sure the cursor wraps when it is required */
  223.  
  224. cmwrap(fd)
  225. FILE *fd;
  226. {
  227.                 /* This happens for console automatically */
  228.                 /* and we assume the same for other devices */
  229. }
  230.  
  231. /* cmcls - Clear the screen.  Only invoked if source is a CRT.  Return
  232. ** TRUE iff we think the operation succeeded.
  233. **/
  234.  
  235. cmcls()
  236. {
  237.   if (console)
  238.     cputs("\033[2J");        /* home and clear screen: ESC [ 2 J */
  239.   else
  240.     cmputc(FORMFEED);        /* for other terminal try a formfeed */
  241.   return(TRUE);            /* assume it worked */
  242. }
  243.  
  244. /* cmceol - Clear to end of line.  Only invoked on a CRT.  Return
  245. ** TRUE iff we think we succeeded.
  246. **/
  247.  
  248. cmceol()
  249. {
  250.   if (console) {
  251.     cputs("\033[K");        /* erase to end-of-line: ESC [ k */
  252.     return(TRUE);
  253.   }
  254.   else
  255.     return(FALSE);        /* say we can't do it on other terminals */
  256. }
  257.  
  258.  
  259. /* cmupl - Moves up one line in the display without changing column
  260. ** position.  Should not wrap to bottom of screen or cause destructive
  261. ** downward scrolling.  Only invoked on a CRT.  Returns TRUE iff we
  262. ** think the operation succeeded.
  263. **/
  264.  
  265. cmupl()
  266. {
  267.   if (console) {
  268.     cputs("\033[A");        /* up one line: ESC [ A */
  269.     return(TRUE);
  270.   }
  271.   else
  272.     return(FALSE);        /* assume other terminals are incapable */
  273. }
  274.  
  275. /* cmcpos - Returns current column position on display.  If the
  276. ** command source is not the console, the column position currently
  277. ** stored in the CSB is returned.
  278. **/
  279.  
  280. int
  281. cmcpos()
  282. {
  283.   int nscan;            /* # of items successfully scanned in */
  284.                 /* cursor position report */
  285.   int row,col;            /* reported cursor position */
  286.  
  287.   if (console) {
  288.     cputs("\033[6n");        /* device status report: ESC [ 6 n */
  289.     nscan = cscanf("\033[%d;%dR",&row,&col); /* scan response */
  290. #ifndef RAINBOW
  291.     getch();            /* pick up the carriage return */
  292. #endif
  293.     if (nscan != 2)
  294.       return(cmcsb._cmcol);    /* undecipherable response */
  295.     else
  296.       return(col-1);        /* give back response adjusted for 0-origin */
  297.   }
  298.   else
  299.     return(cmcsb._cmcol);    /* unknown for other than console */
  300. }
  301.  
  302. /* cmflush - Flush all pending input on the input source */
  303.  
  304. cmflush(fd)
  305. FILE *fd;
  306. {
  307.   char junk;
  308.  
  309.   if (console)
  310.     while(kbhit())
  311.       getch();
  312.   else
  313.     if (fd != NULL) {
  314.       while (read(fileno(fd),&junk,1) == 1); /* flush other terminal */
  315.     fd->_cnt = 0;
  316.     }
  317. }
  318.  
  319. /* cmtset - Initialize the source terminal.  Check if the source is
  320. ** the console, and if so set the console flag as well as the CM_TTY
  321. ** and CM_CRT flags in the CSB.  Otherwise, clear all three flags.
  322. ** In all cases, the column limit in the CSB is set to 79.
  323. **/
  324.  
  325. #include "xdos.h"            /* for interrupt calls */
  326. #define    CARRY    0x01            /* carry in processor flag register */
  327. #define ISCOT    0x02            /* device status flags */
  328. #define    ISCIN    0x01            
  329. #define    ISDEV    0x80            
  330.  
  331. cmtset()
  332. {
  333.   int ifd;
  334.   int ofd;
  335.   union REGS inregs,outregs;        /* registers for DOS call */
  336.   int flags;                /* processor flags after DOS call */
  337.  
  338.   if (cmcsb._cmij != NULL)
  339.     ifd = fileno(cmcsb._cmij);    /* get desired input source */
  340.   if (cmcsb._cmoj != NULL)
  341.     ofd = fileno(cmcsb._cmoj);
  342.  
  343.   if (cmcsb._cmij != NULL) {
  344.     inregs.h.ah = 0x44;            /* IOCTL call */
  345.     inregs.h.al = 0x00;            /* get device info */
  346.     inregs.x.bx = ifd;            /* file handle */
  347.     flags = intdos(&inregs,&outregs);    /* do the call */
  348. #ifdef LATTICE
  349.     if (((flags & CARRY) != 0) || (outregs.x.ax == 0xff)) /* error? */
  350. #else
  351.     if ((outregs.x.cflag != 0) || (outregs.x.ax == 0xff)) /* error? */
  352. #endif
  353.       console = FALSE;            /* then assume nothing */
  354.     else if ((outregs.x.dx & ISDEV) == 0) /* disk file? */
  355.       console = FALSE;            /* then it's not the console */
  356.     else if (outregs.x.dx & (ISCOT | ISCIN)) /* console input or output? */
  357.       console = TRUE;            /* then set flag */
  358.     else
  359.       console = FALSE;            /* otherwise clear it */
  360.   }
  361.   else {
  362.     console = FALSE;
  363.   }
  364.   if (console)
  365.     cmcsb._cmflg |= (CM_TTY | CM_CRT); /* console is a CRT */
  366.   else
  367.     cmcsb._cmflg &= ~(CM_TTY | CM_CRT); /* anything else is not a tty */
  368.   cmcsb._cmcmx = 79;            /* everything has 80 columns */
  369. }
  370.  
  371. /* cmtend - Restore prior terminal state. Nothing needed for PC */
  372.  
  373. cmtend()
  374. {
  375. }
  376.